﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SuperDeepZoom
{
    /// <summary>
    /// Control which allows the overlay of any content on images in the MSI
    /// Based on standard ItemsControl
    /// </summary>
    [TemplateVisualState(Name = "Visible", GroupName = "VisibilityStates")]
    [TemplateVisualState(Name = "Invisible", GroupName = "VisibilityStates")]
    public class SpecialImageOverlay : ItemsControl
    {
        public static readonly DependencyProperty ItemContainerStyleProperty;
        
        SpecialOverlayArranger arranger;
        MultiScaleImage msi;
        ImageArranger imageArranger;

        bool visible = false;
        bool tempDisable = false;

        public SpecialImageOverlay()
        {
            DefaultStyleKey = typeof(SpecialImageOverlay);            
            updateStates(false);            
        }

        void updateStates(bool useTrans)
        {
            if (visible && !tempDisable)
            {
                VisualStateManager.GoToState(this, "Visible", useTrans);
            }
            else
            {
                VisualStateManager.GoToState(this, "Invisible", useTrans);
            }
        }

        void initArranger()
        {
            if (arranger == null)
            {
                if (imageArranger != null && msi != null)
                {
                    arranger = new SpecialOverlayArranger(imageArranger, msi);
                    updateChildren();
                }
            }
        }

        void updateChildren()
        {            
            if (arranger != null)
            {
                if (this.visible)
                {
                    arranger.update();
                }
            }
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is SpecialImageOverlayItem;
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new SpecialImageOverlayItem();
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            var cont = element as SpecialImageOverlayItem;
            if (cont != null)
            {
                if (ItemContainerStyle != null)
                {
                    cont.Style = ItemContainerStyle;
                }
                if (item != null)
                {
                    var val = (System.Collections.Generic.KeyValuePair<int, object>)item;
                    arranger.Add(val.Key, cont);                   
                }
            }

            base.PrepareContainerForItemOverride(element, item);
        }

        protected override void ClearContainerForItemOverride(DependencyObject element, object item)
        {
            var cont = element as SpecialImageOverlayItem;
            if (cont != null)
            {
                if (item != null)
                {
                    var val = (System.Collections.Generic.KeyValuePair<int, object>)item;
                    arranger.Remove(val.Key);
                }
            }
            base.ClearContainerForItemOverride(element, item);
        }

        internal ImageArranger ImageArranger
        {
            set
            {
                if (imageArranger != null)
                {
                    imageArranger.ArrangeAnimationComplete -= new EventHandler(imageArranger_ArrangeAnimationComplete);
                    imageArranger.ImagesRearranged -= new EventHandler(imageArranger_ImagesRearranged);
                }

                imageArranger = value;
                imageArranger.ArrangeAnimationComplete += new EventHandler(imageArranger_ArrangeAnimationComplete);
                imageArranger.ImagesRearranged += new EventHandler(imageArranger_ImagesRearranged);
                
                initArranger();
            }
        }

      
        public MultiScaleImage MultiScaleImage
        {
            set
            {
                if (msi != null)
                {
                    msi.ViewportChanged -= new RoutedEventHandler(msi_ViewportChanged);
                }

                msi = value;
                
                msi.ViewportChanged += new RoutedEventHandler(msi_ViewportChanged);                
                initArranger();
            }
        }

        void msi_ViewportChanged(object sender, RoutedEventArgs e)
        {
            updateChildren();
        }

        void imageArranger_ImagesRearranged(object sender, EventArgs e)
        {
            tempDisable = true;
            updateStates(true);
        }

        void imageArranger_ArrangeAnimationComplete(object sender, EventArgs e)
        {
            tempDisable = false;
            updateStates(true);
            updateChildren();            
        }

        public Style ItemContainerStyle
        {
            get
            {
                return GetValue(ItemContainerStyleProperty) as Style;
            }
            set
            {
                SetValue(ItemContainerStyleProperty, value);
            }
        }

        public bool IsVisible
        {
            get
            {
                return visible;
            }
            set
            {
                visible = value;
                updateStates(true);
                updateChildren();
            }
        }

        static SpecialImageOverlay()
        {
            ItemContainerStyleProperty = DependencyProperty.Register("ItemContainerStyle", typeof(Style), typeof(SpecialImageOverlay), null);
        }
    }
}
